/**   
* @Title: JBeerDBContext.java
* @Package com.jbeer.framework.db
* @author Bieber
* @date 2014年5月26日 上午10:44:28
* @version V1.0   
*/

package com.jbeer.framework.db;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.sql.DataSource;

import com.jbeer.framework.JBeer;
import com.jbeer.framework.annotation.Column;
import com.jbeer.framework.annotation.Entity;
import com.jbeer.framework.constant.JBeerConstant;
import com.jbeer.framework.exception.ScanClassException;
import com.jbeer.framework.utils.ClassUtils;

/**
* <p>类功能说明:数据访问层上下文</p>
* <p>类修改者	    修改日期</p>
* <p>修改说明</p>
* <p>Title: JBeerDBContext.java</p>
* @author Bieber <a mailto="bieber.jbeer@hotmail.com">bieber.jbeer@hotmail.com</a>
* @date 2014年5月26日 上午10:44:28
* @version V1.0
*/

public class JBeerDBContext {

    private static DataSource datasource;
    
    private static String txPointCut = JBeerConstant.DEFALUT_TX_CLASS_REGEX;
    
    
    private static ConcurrentHashMap<Class<?> , EntityModel> entityCache = new ConcurrentHashMap<Class<?> , EntityModel>();
    
	public static void setDataSource(DataSource datasource){
        if(!JBeer.isStartup()&&JBeerDBContext.datasource==null){
            JBeerDBContext.datasource = datasource;
        }
    }
    
    public static void setTxPointCut(String txPointCut){
    	if(JBeer.isStartup()){
    		return;
    	}
    	JBeerDBContext.txPointCut=txPointCut;
    }
    
    public static String getTxPointCut(){
    	return JBeerDBContext.txPointCut;
    }
    
    public static DataSource getDataSource(){
        return datasource;
    }
    
    public static EntityModel getEntity(Class<?> clazz){
        return entityCache.get(clazz);
    }
    /**
     * 
    * <p>函数功能说明:将table实体注册到缓存中，从而可以避免每次需要反射分析实体类</p>
    * <p>Bieber  2014年6月5日</p>
    * <p>修改者名字 修改日期</p>
    * <p>修改内容</a>  
    * @return void
     */
    protected synchronized static  void registEntity(Class<?>  entityClass,EntityModel model){
        if(!entityCache.contains(entityClass)){
            entityCache.put(entityClass, model);
        }
    }
    
    /**
     * 
    * <p>函数功能说明:初始化DB，注入{@link DataSource}实体</p>
    * <p>Bieber  2014年6月5日</p>
    * <p>修改者名字 修改日期</p>
    * <p>修改内容</a>  
    * @return void
     * @throws ScanClassException 
     */
    public static void initializeDB(DataSource ds) throws ScanClassException{
    	if(JBeer.isStartup()){
    		return;
    	}
        datasource=ds;
        init();
    }
    
    public static void initializeDB() throws ScanClassException{
    	if(JBeer.isStartup()){
    		return;
    	}
    	init();
    }
    
    
    private static void init() throws ScanClassException{
    	Set<Class<?>> classSet = ClassUtils.scanClassesByAnnotation(Entity.class);
        for(Class<?> clazz:classSet){
            Entity entity = clazz.getAnnotation(Entity.class);
            EntityModel model = new EntityModel();
            if(entity.name()==JBeerConstant.DEFAULT_ENTITY_NAME){
                model.setEntityName(clazz.getSimpleName());
            }else{
                model.setEntityName(entity.name());
            }
            model.setEntityType(clazz);
            Collection<Field> fields = ClassUtils.listClassAllFields(clazz, true);
            for(Field field:fields){
                Method getMethod = ClassUtils.searchGetMethod(clazz, field.getName());
                Method setMethod = ClassUtils.searchSetMethod(clazz, field.getName(), field.getType());
                if(setMethod==null||getMethod==null){
                    continue;
                }
                Column column = field.getAnnotation(Column.class);
                ColumnModel cModel = new ColumnModel();
                cModel.setGetMethod(getMethod);
                cModel.setSetMethod(setMethod);
                cModel.setAutoIncreasement(false);
                cModel.setColumnName(entity.columnPrefix()+field.getName());
                cModel.setPrimarykey(false);
                cModel.setType(field.getType());
                if(column!=null){
                	if(!column.name().equals(JBeerConstant.DEFAULT_COLUMN_NAME)){
                        cModel.setColumnName(column.name());
                    }
                    cModel.setAutoIncreasement(column.isAutoGenerate());
                    if(column.isAutoGenerate()){
                        model.setUseGeneratedKeySupport(true);
                        model.setAutoGeneratedColumnName(cModel.getColumnName());
                    }
                    cModel.setPrimarykey(column.isPrimarykey());
                    if(cModel.isPrimarykey()){
                        model.setPrimaryKeyName(cModel.getColumnName());
                    }
                }
                model.registColumn(cModel);
            }
            registEntity(clazz, model);
        }
    }
    
}
